<?php

class AFRoutingException extends AFException {};

class AFRouterMap extends AFQueriable
{
	public $path;
	public $controller;
	public $arguments = array();

	public function __construct($path, $controller, $arguments)
	{
		$this->path = '/^' . str_replace(array('/', '(', ')', '%d', '%s', '%S'), array('\/', '\(', '\)', '([0-9]+)', '([0-9a-z_\.]+)', '([0-9a-zA-Z_\.]+)'), $path) . '$/';
		$this->controller = $controller;
		$this->arguments = $arguments;
	}

/*	public function match($requestedPath)
	{
//		preg_match_all('/^\/view\/([0-9]+)$/', 'view/1', $out, PREG_SET_ORDER);
//		var_dump($out);
//		exit;

		preg_match_all($this->path, $requestedPath, $matches, PREG_SET_ORDER);
		if(count($matches))
		{
			return array_slice($matches[0], 1);
		}
		else
		{
			return NULL;
		}
	}

	public function executeController($matches)
	{
		$this->controller->execute();
	}*/

	public function execute($requestedPath)
	{
		preg_match_all($this->path, $requestedPath, $matches, PREG_SET_ORDER);
		if(count($matches))
		{
			//$this->controller->execute((StdClass)(array_combine($this->arguments, array_slice($matches[0], 1))));
			$values = array_slice($matches[0], 1);
			$params = new AFQueriable();
			for($i=0; $i<count($this->arguments); $i++)
			{
				$params->setQueryValue($this->arguments[$i], $values[$i]);
			}
			(new $this->controller)->execute($params);
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}
}

class AFRouterModule extends AFModule
{
	private $maps = array();
	private $defaultMap = NULL;

	public function map($path, $controller /* , args, ... */)
	{
		if(is_array($path))
		{
			foreach($path as $k => $v)
			{
				$this->maps[$k] = new AFRouterMap(trim($k, '/.'), $v, array_slice(func_get_args(), 2));
			}
		}
		else
		{
			$this->maps[$path] = new AFRouterMap(trim($path, '/.'), $controller, array_slice(func_get_args(), 2));
		}
		return $this;
	}

	public function defaultMap($controller)
	{
		$this->defaultMap = $controller;
		return $this;
	}

	public function route()
	{
		$requestedPath = trim($_SERVER['QUERY_STRING'], '/.');
		foreach($this->maps as $key => $map)
		{
			if($map->execute($requestedPath))
			{
				return TRUE;
			}
		}

		if(!$this->defaultMap)
		{
			throw new AFRoutingException('No default route found.', 1);
		}

		$this->defaultMap->execute($requestedPath);
	}
}

?>
